package com.woniuxueyuan.util;

import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 怎么理解线程安全问题：在没有同步干预的情况下，
 *                  程序的运行结果和预期的一样就是安全，反之就是不安全
 *       不安全代码：对共享变量出现了非原子性操作
 *       共享：线程共享
 *       非原子性操作：++，--等计算
 *
 *       怎么解决：加锁
 *    1.悲观锁 ：线程走到代码前，一定有其他线程抢
 *       1.1 本地锁（jdk锁）
 *       synchronized
 *       作用:可以使方法或者代码变成同步代码块,同步代码块/或者同步代码同一时间只能有一个线程进去
 *
 *       lock：java锁接口：ReentrantLock（重入锁）
 *       ReentrantLock使用步骤
 *       1：创建锁对象
 *       2.加锁
 *       3.释放锁
 *
 *
 *       1.2 分布锁
 *       要借助第三方工具（比如Lredis就可以实现分布式锁）
 *
 *
 *    2.乐观锁 ：线程走到代码前，一定没有其他线程抢
 */
@Component
public class Count {
    public int count = 10000;
    ReentrantLock reentrantLock = new ReentrantLock();
    public void sub() {
        try {
//            reentrantLock.lock();//加锁，这个拿不到锁一直等
            boolean b = reentrantLock.tryLock(2, TimeUnit.SECONDS);//线程尝试获取锁，获取到返回true，获取不到返回false,等待两秒之后获取不到返回false
            if(b) {
                if (count > 0) {
                    count--;  //1.读取原来的值
                    //2.对读取原来的值减一




                    //3.把计算后值重新赋值
                }
            }else {
                System.out.println("获取不到锁");
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        finally {
            //判断当前线程是否获取到锁，只能释放当前线程自己加的锁
            if(reentrantLock.isLocked() && reentrantLock.isHeldByCurrentThread())
            reentrantLock.unlock();//释放锁
        }

        }

}


//    public int count = 10000;
//
//    public void sub() {
//      synchronized (this){
//
//        if (count > 0) {
//            count--;  //1.读取原来的值
//            //2.对读取原来的值减一
//            //3.把计算后值重新赋值
//
//        }
//    }
//    }
//}

